package com.wft.design.oauth.controller;

import com.wft.design.common.security.annotation.PreAuthorize;
import com.wft.design.common.security.bean.AccessToken;
import com.wft.design.common.security.bean.Authentication;
import com.wft.design.common.security.service.AuthenticationManager;
import com.wft.design.oauth.constant.GrantType;
import com.wft.design.oauth.entity.OauthClient;
import com.wft.design.oauth.entity.OauthParameter;
import com.wft.design.oauth.service.*;
import com.wft.design.oauth.factory.GrantModeStrategyFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.util.Assert;
import org.springframework.util.Base64Utils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * @author WFT
 * @date 2019/12/20
 * description: Oauth授权控制器
 */
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/oauth")
public class OauthGrantController {

    private final GrantModeStrategyFactory grantModeStrategyFactory;
    private final AuthenticationManager authenticationManager;
    private final GrantCodeService grantCodeService;
    private final OauthClientService clientService;
    private final TokenService tokenService;

    private final static String BASIC = "Basic";

    /**
     * 获取 AccessToken
     * @param parameter 请求参数
     * @param basicAuth 客户端信息
     * @return com.wft.design.common.security.bean.AccessToken
     */
    @PostMapping(value = "/token")
    public AccessToken getToken(@Validated(value = OauthParameter.OauthValidation.class) @RequestBody OauthParameter parameter,
                                @RequestHeader(value = HttpHeaders.AUTHORIZATION) String basicAuth){
        //  使用Base64解码
        basicAuth = basicAuth.replace(BASIC,"").trim();
        basicAuth = new String(Base64Utils.decodeFromString(basicAuth));
        String[] fields = basicAuth.split(":");
        Assert.isTrue(fields.length == 2,"客户端信息有误");
        //  获取客户端Id和密钥
        parameter.setClientId(fields[0]);
        parameter.setClientSecret(fields[1]);

        //  获取授权策略
        GrantModeService grantModeService = this.grantModeStrategyFactory.getGrantModeService(parameter.getGrantType());
        Assert.notNull(grantModeService,"当前系统不支持此授权模式");
        Authentication authentication = grantModeService.checking(parameter);
        //  生成Token
        return this.tokenService.generateToken(authentication,parameter.getRememberMe());
    }

    /**
     * 申请授权码
     * @param clientId 客户端Id
     * @return java.lang.Long
     */
    @PreAuthorize
    @GetMapping(value = "/code/{clientId}")
    public Long getGrantCode(@PathVariable(value = "clientId") String clientId){
        //  校验客户端Id是否存在
        OauthClient client = this.clientService.selectById(clientId);
        Assert.notNull(client,"客户端Id不存在");
        //  获取当前用户Id
        Long accountId = this.authenticationManager.getAuthentication().getAccountId();
        Assert.isTrue(GrantType.authorization_code.toString().equals(client.getGrantType()),"当前客户端不支持授权码模式");
        //  创建授权码
        return this.grantCodeService.createGrantCode(accountId,client);
    }

}
